// Copyright (C) 2010 Félix Cloutier.

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License 2.0 for more details.

// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/

#include "JitRecompiler.h"

#define INST(name) \
	void JitRecompiler::name(UGeckoInstruction inst, JitFunctionContext& functionContext)

namespace LLVMJit
{

INST(sc)
{
	llvm::IRBuilder<>& builder = functionContext.GetBuilder();

	llvm::Value* indexes[2];
	indexes[0] = builder.getInt32(0);
	indexes[1] = builder.getInt32(9); // 9 is the index of Exceptions in ppcState
	
	// The interpreter uses an atomic or, but I'm not sure why.
	llvm::Value* ppcState = functionContext.GetPowerPCState();
	llvm::Value* exceptionsPointer = builder.CreateGEP(ppcState, indexes, indexes + 1);
	llvm::Value* exceptions = builder.CreateLoad(exceptionsPointer);
	llvm::Value* ored = builder.CreateOr(exceptions, builder.getInt32(EXCEPTION_SYSCALL));
	builder.CreateStore(exceptions, exceptionsPointer);

	llvm::Function* yield = bindings->GetBinding(JitBindings::Yield);
	builder.CreateCall(yield, functionContext.GetCoroutine());
}

#pragma mark -
INST(mcrfs)
{
#ifndef _MSC_VER
#warning	Implement me!
#endif
	Default(inst, functionContext);
}

INST(mffsx)
{
#ifndef _MSC_VER
#warning	Implement me!
#endif
	Default(inst, functionContext);
}

INST(mtfsb0x)
{
#ifndef _MSC_VER
#warning	Implement me!
#endif
	Default(inst, functionContext);
}

INST(mtfsb1x)
{
#ifndef _MSC_VER
#warning	Implement me!
#endif
	Default(inst, functionContext);
}

INST(mtfsfix)
{
#ifndef _MSC_VER
#warning	Implement me!
#endif
	Default(inst, functionContext);
}

INST(mtfsfx)
{
#ifndef _MSC_VER
#warning	Implement me!
#endif
	Default(inst, functionContext);
}

INST(mcrxr)
{
#ifndef _MSC_VER
#warning	Implement me!
#endif
	Default(inst, functionContext);
}

INST(mfcr)
{
#ifndef _MSC_VER
#warning	Implement me!
#endif
	Default(inst, functionContext);
}

INST(mfmsr)
{
#ifndef _MSC_VER
#warning	Implement me!
#endif
	Default(inst, functionContext);
}

INST(mfsr)
{
#ifndef _MSC_VER
#warning	Implement me!
#endif
	Default(inst, functionContext);
}

INST(mfsrin)
{
#ifndef _MSC_VER
#warning	Implement me!
#endif
	Default(inst, functionContext);
}

INST(mtmsr)
{
#error Implement me!
}

INST(mtsr)
{
#ifndef _MSC_VER
#warning	Implement me!
#endif
	Default(inst, functionContext);
}

INST(mtsrin)
{
#ifndef _MSC_VER
#warning	Implement me!
#endif
	Default(inst, functionContext);
}

INST(mfspr)
{
#ifndef _MSC_VER
#warning	Implement me!
#endif
	Default(inst, functionContext);
}

INST(mftb)
{
#ifndef _MSC_VER
#warning	Implement me!
#endif
	Default(inst, functionContext);
}

INST(mtcrf)
{
#ifndef _MSC_VER
#warning	Implement me!
#endif
	Default(inst, functionContext);
}

INST(mtspr)
{
#ifndef _MSC_VER
#warning	Implement me!
#endif
	Default(inst, functionContext);
}

INST(crand)
{
#ifndef _MSC_VER
#warning	Implement me!
#endif
	Default(inst, functionContext);
}

INST(crandc)
{
#ifndef _MSC_VER
#warning	Implement me!
#endif
	Default(inst, functionContext);
}

INST(creqv)
{
#ifndef _MSC_VER
#warning	Implement me!
#endif
	Default(inst, functionContext);
}

INST(crnand)
{
#ifndef _MSC_VER
#warning	Implement me!
#endif
	Default(inst, functionContext);
}

INST(crnor)
{
#ifndef _MSC_VER
#warning	Implement me!
#endif
	Default(inst, functionContext);
}

INST(cror)
{
#ifndef _MSC_VER
#warning	Implement me!
#endif
	Default(inst, functionContext);
}

INST(crorc)
{
#ifndef _MSC_VER
#warning	Implement me!
#endif
	Default(inst, functionContext);
}

INST(crxor)
{
#ifndef _MSC_VER
#warning	Implement me!
#endif
	Default(inst, functionContext);
}

INST(mcrf)
{
#ifndef _MSC_VER
#warning	Implement me!
#endif
	Default(inst, functionContext);
}

INST(rfi)
{
#error Implement me!
}

INST(rfid)
{
#ifndef _MSC_VER
#warning	Implement me!
#endif
	Default(inst, functionContext);
}

// was commented out in Interpreter.h
/*
INST(sync)
{
#ifndef _MSC_VER
#warning	Implement me!
#endif
	Default(inst, functionContext);
}
*/

INST(isync)
{
#ifndef _MSC_VER
#warning	Implement me!
#endif
	Default(inst, functionContext);
}


}